﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System.Runtime.Serialization;
using System;
using System.Xml.Serialization;
using System.Threading;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BrainTechLLC.ThreadSafeObjects;

namespace BrainTechLLC
{
    [Serializable]
    [DataContract]
    public class LookCommand : Command, ICommandInfo
    {
        public override string HelpText { get { return "Looks in the room, or at the object/character/creature specified"; } }
        public override string Example { get { return "(1) look scary monster (2) look"; } }

        [NonSerialized, XmlIgnore]
        public static List<string> Words = new List<string>() { "LOOK" };

        public override List<string> FirstWords { get { return Words; } }

        public override CommandToPerform CreateCommand(IGameThing source, string first, string input)
        {
            return CommandFactory.CreateLook(source.AssociatedID, input);            
        }

        public override bool CheckIsValid(IGameThing source, string first, string input)
        {
            return true;
        }

        [MethodVisible]
        public static List<PerceivedEventAndAudience> PerformLookCommand(CommandToPerform cmd, IGameThing source, IGameThing target, PropertyData args, PropertyData modifyingArguments)
        {
            List<PerceivedEventAndAudience> events = new List<PerceivedEventAndAudience>();
            GameThingBaseClass hasName = source as GameThingBaseClass;
            ICanBeNotified notify = source as ICanBeNotified;
            string lookParams = (cmd.UserInput == null) ? string.Empty : cmd.UserInput;

            if (hasName != null)
            {
                string[] strings = lookParams.Split(" ".ToCharArray(), 2, StringSplitOptions.None);

                EventToPerceive evt = new EventToPerceive()
                {
                    Sources = new AssociatedIDCollection(notify.AssociatedID),
                };

                GameLocation location = hasName.GameLocation;

                // TESTING ONLY
                //LockList locked = new LockList();
                //locked.ListToLock.Add(location);
                //locked.ListToLock.Add(hasName);

                //while (!locked.TryAquireLock())
                //{
                //    Console.WriteLine("TryAquireLock() returned false");
                //    Thread.Sleep(10);
                //}

                try
                {
                    if (strings.Length == 0 || (strings.Length == 1 && string.IsNullOrEmpty(strings[0])))
                    {
                        var thingList = location.ShowThings(source as ICanObserveViewable);
                        evt._event = new Event(thingList.BuildList(Environment.NewLine, (s) => s), ViewType.See);
                        events.Add(new PerceivedEventAndAudience() { Event = evt, Audience = new AssociatedIDCollection(notify.AssociatedID) });
                    }
                    else if (strings.Length >= 1)
                    {
                        string matched;
                        List<MatchAndStrength> matchedItems = null;
                        float f = location.FindByKeyword(lookParams, 0f, out matched, ref matchedItems);
                        if (matchedItems != null && matchedItems.Count > 0)
                        {
                            evt._event = new Event(String.Format("{0} - {1} - {2}", f, matched, matchedItems[0].MatchedItem.ToString()), ViewType.See);
                            events.Add(new PerceivedEventAndAudience() { Event = evt, Audience = new AssociatedIDCollection(notify.AssociatedID) });
                        }
                    }
                }
                finally
                {
                    // END TESTING
                    //locked.ReleaseLock();
                }
            }
            return events;
        }

    }

    public static partial class CommandFactory
    {
        [MethodVisible]
        public static CommandToPerform CreateShowNameCommand(long showNameOf, long showTo)
        {
            CommandToPerform cmd = new CommandToPerform()
            {
                ApplyToID = showTo,
                Arguments = new PropertyData(new IdentifierAndValue() { Identifier = "TargetID", Value = showNameOf }),
                PerformMethod = new Method(typeof(CommandFactory).FullName, "ShowName")
            };
            return cmd;
        }

        [MethodVisible]
        public static CommandToPerform CreateLook(long source, string lookParams)
        {
            CommandToPerform cmd = new CommandToPerform()
            {
                ApplyToID = source,
                UserInput = lookParams,
                PerformMethod = new Method("LookCommand", "PerformLookCommand")
            };
            return cmd;
        }

        [MethodVisible]
        public static List<PerceivedEventAndAudience> ShowName(CommandToPerform cmd, IGameThing source, IGameThing target, PropertyData args, PropertyData modifyingArguments)
        {
            List<PerceivedEventAndAudience> events = new List<PerceivedEventAndAudience>();

            EventToPerceive evt = new EventToPerceive()
            {
                Sources = new AssociatedIDCollection(source.AssociatedID),
                Targets = new AssociatedIDCollection(target.AssociatedID),
                _event = new Event(target.Name, ViewType.See)
            };

            events.Add(new PerceivedEventAndAudience() { Event = evt, Audience = new AssociatedIDCollection(source.AssociatedID) });


            return events;
        }
    }
}
